package com.walle.nio;

import java.io.BufferedReader;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

/**
 * @author zhangjiapeng
 * @Package com.walle.nio
 * @Description: ${todo}
 * @date 2019/1/21 13:35
 */
public class TimeServer implements Runnable {

    private Selector selector;

    private static  final int  PORT = 9999;

    private ServerSocketChannel serverSocketChannel;

    private volatile boolean stop;

    private SimpleDateFormat sdf;

    public static void main(String[] args) {
        new Thread(new TimeServer()).start();
    }

    public TimeServer() {
        try {
            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            stop = false;
            selector = Selector.open();
            serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.socket().bind(new InetSocketAddress("127.0.0.1",PORT),1024);
            serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);
            System.out.println("Time Server Started And Listening " + PORT);
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    @Override
    public void run() {

        while(!stop){
            try {
                selector.select(1000);
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectedKeys.iterator();
                while(iterator.hasNext()){
                    SelectionKey selectionKey = iterator.next();
                    iterator.remove();
                    handleInput(selectionKey);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private  void handleInput(SelectionKey selectionKey) throws IOException {
        if(selectionKey.isValid()){
            if(selectionKey.isAcceptable()){
                ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
                SocketChannel socket = serverSocketChannel.accept();
                socket.configureBlocking(false);
                socket.register(selector,SelectionKey.OP_READ);
            }
            if(selectionKey.isReadable()){
                SocketChannel socket = (SocketChannel) selectionKey.channel();
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                int readBytes = socket.read(buffer);
                if (readBytes > 0) {
                    buffer.flip();
                    byte[] bytes = new byte[buffer.remaining()];
                    buffer.get(bytes);
                    String msg = new String(bytes,"UTF-8");
                    System.out.println("received msg :" + msg);
                    doWrite(socket);
                }else if(readBytes < 0){
                    selectionKey.cancel();
                    socket.close();
                }else{
                }
            }
        }
    }

    private void doWrite(SocketChannel socket) throws IOException {
        String currentTime = sdf.format(new Date());
        byte[] bytes = currentTime.getBytes();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        buffer.put(bytes);
        buffer.flip();
        socket.write(buffer);
    }

    public void stop(){
        this.stop = true;
    }

}
